<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>九宫格</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        
        ul {
            width: 320px;
            height: 320px;
            position: relative;
            left: 500px;
            top: 150px;
            border: 1px solid purple;
        }
        
        li {
            list-style: none;
            position: absolute;
            width: 100px;
            text-align: center;
            line-height: 100px;
            font-size: 18px;
            height: 100px;
            user-select: none;
        }
    </style>
</head>

<body>
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>

    <script>
        var oUl = document.querySelector("ul"); //获取第一个ul的dom
        var aLis = document.querySelectorAll("li"); //获取所有的li
        var lt = mt = 10; //margin左和margin右值
        //控制颜色的变化
        function RandColor() {
            return Math.floor(Math.random() * 256); //定义一个函数返回一个0-255之间的值
        }
        for (var i = 0; i < aLis.length; i++) {
            aLis[i].style.left = (i % 3) * (100 + lt) + "px"; //通过取余运算对列排列
            aLis[i].style.top = Math.floor(i / 3) * (100 + mt) + "px"; //通过向下取整进行行排列
            aLis[i].style.backgroundColor = "rgb(" + RandColor() + "," + RandColor() + "," + RandColor() + ")"; //背景色
            aLis[i].innerText = i + 1; //li内的内容填充
            aLis[i].onmousedown = function(e) { //添加事件
                var evt = e || event;
                var dragNode = this; //把DOM对象(this)赋给dragNode,因为this指向问题,需要保存this
                var cloneNode = dragNode.cloneNode(); //克隆一个元素留在原地
                dragNode.style.zIndex = 2; //拖拽时置于顶部
                dragNode.style.border = "2px solid black"; //突出样式
                oUl.replaceChild(cloneNode, dragNode); //把拖拽节点换成克隆节点
                oUl.appendChild(dragNode); //把拖拽节点放到oUl尾部
                var x = evt.offsetX; //鼠标在事件源的位置
                var y = evt.offsetY; //鼠标在事件源的位置
                document.onmousemove = function(e) {
                    var evt = e || event;
                    var _x = evt.clientX - x - oUl.offsetLeft; //求坐标
                    var _y = evt.clientY - y - oUl.offsetTop;

                    _x = _x < 0 ? 0 : _x > oUl.offsetWidth - 100 ? oUl.offsetWidth - 100 : _x;
                    _y = _y < 0 ? 0 : _y > oUl.offsetHeight - 100 ? oUl.offsetHeight - 100 : _y;

                    dragNode.style.left = _x + "px";
                    dragNode.style.top = _y + "px";

                }
                document.onmouseup = function() {
                    var arr = []; //定义空数组用来存放dragNode每一个兄弟元素的坐标
                    aLis = oUl.children;
                    for (var i = 0; i < aLis.length - 1; i++) { //开始存放
                        arr.push({
                            left: aLis[i].offsetLeft,
                            top: aLis[i].offsetTop
                        })
                    }
                    var _x = dragNode.offsetLeft;
                    var _y = dragNode.offsetTop;
                    var resurt = []; //定义一个空的结果数组
                    var num = Infinity; //定义一个值用来保存结果的最小值
                    arr.forEach(function(item) {
                        resurt.push(Math.sqrt(Math.pow(Math.abs(_x - item.left), 2) + Math.pow(Math.abs(_y - item.top), 2)));
                        if (num > Math.sqrt(Math.pow(Math.abs(_x - item.left), 2) + Math.pow(Math.abs(_y - item.top), 2))) {
                            num = Math.sqrt(Math.pow(Math.abs(_x - item.left), 2) + Math.pow(Math.abs(_y - item.top), 2));
                        }
                    })
                    num = resurt.indexOf(num); //把resurt数组中的最小值的索引赋给num
                    //交换位置
                    dragNode.style.left = aLis[num].style.left;
                    dragNode.style.top = aLis[num].style.top;
                    aLis[num].style.left = cloneNode.style.left;
                    aLis[num].style.top = cloneNode.style.top;
                    //回置样式
                    dragNode.style.zIndex = 1;
                    dragNode.style.border = "none";
                    oUl.removeChild(cloneNode);
                    document.onmouseup = null;
                    document.onmousemove = null;
                }
            }
        }
    </script>
</body>

</html>